package cmd

import (
	"context"
	"os"
	"os/signal"
	"strconv"
	"syscall"

	"gitee.com/tonyjia/gb28181/pkg/config"
	"gitee.com/tonyjia/gb28181/pkg/gb"
	"gitee.com/tonyjia/gb28181/pkg/gbsip"
	"gitee.com/tonyjia/gb28181/pkg/model"
	"gitee.com/tonyjia/gb28181/pkg/option"
	"github.com/ghettovoice/gosip/sip"
	log "github.com/sirupsen/logrus"
	"golang.org/x/sync/errgroup"
)

/**
 * @Description
 * @Author lulili
 * @Date 2024/10/23 8:59
 */

type Server struct {
	server *gbsip.Server
	ctx    context.Context
}

type SipConfig struct {
	SipOption *option.SIPOptions
}

type ISipCommander interface {
	// Register 注册到上级平台接口，需要传递注册的有效期，单位为s,不传递默认值为3600秒
	Register(model.SipServerInfo, int) error
	// GetDeviceInfo 获取设备信息
	GetDeviceInfo(model.Device) error
	// GetChannelInfo 获取设备通道信息
	GetChannelInfo(device model.Device) error
	// Play 点播
	Play(device model.Device, detail model.MediaServer, channel model.Channel) (model.StreamInfo, error)
	// StopPlay 停止点播
	StopPlay(channel model.Channel, device model.Device) error
	// SubscribeCatalog  订阅
	SubscribeCatalog(d model.Device) error
	// NotifyCatalog 将自身的目录变动通知到上级平台
	NotifyCatalog(channel []model.Channel, device model.Device) error
}

func NewServer(sipComm *gbsip.SipCommander, funcMap map[int]config.Process) *Server {
	sipConfig := &config.SIPOptions{
		Ip:        sipComm.SipInfo.IP,
		Port:      strconv.Itoa(sipComm.SipInfo.Port),
		Domain:    sipComm.SipInfo.ReginID,
		Id:        sipComm.SipInfo.DeviceID,
		Password:  sipComm.SipInfo.PassWord,
		UserAgent: "gb-sip",
	}
	s := &Server{
		gbsip.NewServer(
			&gbsip.SipConfig{
				SipOption:  sipConfig,
				HandlerMap: createHandlerMap(),
				Callback:   funcMap,
			}),
		context.Background(),
	}
	return s
}

func (s *Server) Run() error {
	closeCh := listenAndServeWithSignal()
	go func() {
		<-closeCh
		if err := s.Close(); err != nil {
			log.Error(err)
		}
		log.Info("gbserver shutdown....")
	}()

	eg, ctx := errgroup.WithContext(s.ctx)
	defer ctx.Done()

	eg.Go(func() error {
		return s.ListenTCP()
	})

	eg.Go(func() error {
		return s.ListenUDP()
	})

	if err := eg.Wait(); err != nil {
		return err
	}
	return nil
}

func (s *Server) ListenTCP() error {
	return s.server.ListenTCP()
}

func (s *Server) ListenUDP() error {
	return s.server.ListenUDP()
}

func (s *Server) Close() error {
	_ = s.server.Shutdown()
	log.Info("gb server shutdown...")
	return nil
}
func listenAndServeWithSignal() <-chan struct{} {
	closeChan := make(chan struct{})
	sigCh := make(chan os.Signal, 1)
	// 监听并捕获 sighup（挂起）、sigquit(退出)、sigterm（终止）、sigint（终端）这些信号量，并将这些信号量写入到sigCh管道中
	signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)

	go func() {
		sig := <-sigCh
		switch sig {
		case syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
			closeChan <- struct{}{}
		}
	}()
	return closeChan
}

func createHandlerMap() gbsip.RequestHandlerMap {
	m := make(map[sip.RequestMethod]func(req sip.Request, tx sip.ServerTransaction))
	m[sip.REGISTER] = gb.RegisterHandler
	m[sip.MESSAGE] = gb.MessageHandler
	m[sip.NOTIFY] = gb.NotifyHandler
	m[sip.SUBSCRIBE] = gb.SubscribeHandler
	m[sip.INVITE] = gb.InviteHandler
	m[sip.BYE] = gb.ByeHandler
	return m
}
